/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package racer.client.gui;

/**
 *
 * @author Lieven
 */


import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import racer.client.gui.entities.CarEntity;
import racer.client.gui.tiles.Tile;
import racer.client.gui.tiles.TileTypeNeighbours;


public class Calculate {

    private static double collisionPoint_x;
    private static double collisionPoint_y;
    //ARE USED !!
    private static boolean mapcollision_active = false;
    private static boolean movingLeftOnScreen = false;
    private static boolean movingRightOnScreen = false;
    private static boolean movingUpOnScreen = false;
    private static boolean movingDownOnScreen = false;
    private static boolean movingDiagonalOnScreen = false;
    private static boolean driving_forward=false;
    private static boolean driving_backwards=false;
    //cruciaal bij collision detection
    //later gelijkzetten aan id van finishline
    private static int active_tile_this_player=1;
    private static int active_tile_opponent=1;
    private static int previous_active_tile=0;    
    private static int angle;
    private static booleans bol;
    private static CarEntity this_player;
    private static CarEntity opponent;
    private static BufferedImage current_car_image;
    private static HashMap map_tiletype_switchNumberCol;
    private static HashMap map_tileId_tileObjectCol;
    private static HashMap map_angleId_bufferedImageObjectCol;
    private static Double moveSpeed = 150.0;
    

  /**
  * Methods to init/set needed hashmaps (some shared with game.jave and tiledmap.java)
  * 
  * */    
    //set at the beginning of the game
    public static void initMap_tiletype_switchNumber(){
        
               map_tiletype_switchNumberCol=new HashMap(); 
           //per type pic een cijfer (switch case -> int)
           
           map_tiletype_switchNumberCol.put("H","1");
           map_tiletype_switchNumberCol.put("HFIN","1");
           map_tiletype_switchNumberCol.put("V","2");
           map_tiletype_switchNumberCol.put("VFIN","2");
           map_tiletype_switchNumberCol.put("K1","3");
           map_tiletype_switchNumberCol.put("K2","4");
           map_tiletype_switchNumberCol.put("K3","5");
           map_tiletype_switchNumberCol.put("K4","6");           
    }    

    //only set when map has been build
    public static void setMap_tileId_tileObject(HashMap map_tileId_tileObject){
        map_tileId_tileObjectCol=map_tileId_tileObject;   
    }

    public static void setMap_angleId_bufferedImageObject(HashMap map_angleId_bufferedImageObject){
       map_angleId_bufferedImageObjectCol=map_angleId_bufferedImageObject;   
    }    
    
    
 /**
 *Retrieves tile object identified by its id,gets the type of the tile and returns ~ int for use in switch/case
 *<br>
 * @param  tile2check tile-id
 * @return int switch/case integer
 * @see Tile

 */                  
private static int tileTypeCheck(int tile2check){

        Tile tee = (Tile)map_tileId_tileObjectCol.get(tile2check);
        return Integer.parseInt(map_tiletype_switchNumberCol.get(tee.type).toString());

    }        
    
    
 /**
 *Calculates the new car position depending on the driving direction/angle of the car (uses angle var and booleans -> see booleans class).
 *<br>Difference between diagonal movement (4 kwadrants,0-90,90-180,180-270,270-360) and normal movement (horizontal 0,180,360 or vertical 90,270 degrees) 
  * <br><b>To Piet & Benjamin</b>: Non-diagonal movement is calculated using carEntity methods,diagonal not..so perhaps its best to do this also in the future.
 * @param  game Game-object for using its getters/setters (get carEntity objects (player and opponent) and set new position/new collision point(debug only))
  * @param delta time based (see gameLoop in game.java) factor
 * @see Tile
  * @see booleans
  * @see Game.InputHandler#keyPressed(KeyEvent)

 */           
    
    
  
public static void new_car_position(Game game,long delta){
            
            
            this_player=game.getThisPlayer();
            bol=game.getBooleans();
            angle=game.getAngle();            

            //check en prentje goed zetten
            movingLeftOnScreen = bol.getmovingLeftOnScreen();
            movingRightOnScreen = bol.getmovingRightOnScreen();
            movingUpOnScreen = bol.getmovingUpOnScreen();
            movingDownOnScreen = bol.getmovingDownOnScreen();
            movingDiagonalOnScreen = bol.getmovingDiagonalOnScreen();
            driving_forward=bol.getvooruitrijden();
            driving_backwards=bol.getachteruitrijden();
                
           if((movingDiagonalOnScreen)&&((driving_forward)||(driving_backwards))){
                System.out.println("INLOOP: movingDiagonalOnScreen = true - moving diagonally");
                

                double x2=this_player.getX();
                double y2= this_player.getY();
                int interval=2;
                //int correctie1=4;
                int fake_angle_90=80;
                int fake_angle_270=260;
                
                if((angle >0)&&(angle < fake_angle_90)){
                    if(driving_forward){
                        x2-=interval;
                        y2-=interval;                                                
                    }else if(driving_backwards){
                        x2+=interval;
                        y2+=interval;                        
                    }                    

                }else if((angle >fake_angle_90)&&(angle <180)){ 
                    if(driving_forward){
                        x2+=interval;
                        y2-=interval;                        
                    }else if(driving_backwards){
                        x2-=interval;
                        y2+=interval;                        
                    }

                //afhandelen speciale beweging
                }else if((angle >180)&&(angle < fake_angle_270)){ 
                    if(driving_forward){
                        x2+=interval;
                        y2+=interval;                        
                    }else if(driving_backwards){
                        x2-=interval;
                        y2-=interval;                        
                    }                    

                }else if((angle > fake_angle_270)&&(angle <360)){ 
                    if(driving_forward){
                        x2-=interval;
                        y2+=interval;
                    }else if(driving_backwards){
                        x2+=interval;
                        y2-=interval;
                    }                    

                    
                }
                //this_player.setXY(x2+x9, y2+y9);
                this_player.setXY(x2, y2);
                collisionPoint_x=x2;
                collisionPoint_y=y2;
            }            //(naar voor duwen) = naar -x ,links bewegen
           else if((!movingDiagonalOnScreen)&&((driving_forward)||(driving_backwards))){
                
            this_player.setHorizontalMovement(0);
            if ((movingLeftOnScreen) && (!movingRightOnScreen)) {
                this_player.setHorizontalMovement(-moveSpeed);
            }
            
            else if ((movingRightOnScreen) && (!movingLeftOnScreen)) {
                this_player.setHorizontalMovement(moveSpeed);
            }	
            
            this_player.setVerticalMovement(0);
            
            if (movingUpOnScreen && !movingDownOnScreen) {
               // if (movingLeftOnScreen){
                //this_player.setHorizontalMovement(-moveSpeed);
                //}
                this_player.setVerticalMovement(-moveSpeed);
            }
            
            else if (movingDownOnScreen && !movingUpOnScreen){
                this_player.setVerticalMovement(moveSpeed);
            }

            //for (Entity entity : entities)
                //if (!movingDiagonalOnScreen){
                this_player.move(delta);            
           }else{
                this_player.setHorizontalMovement(0);
                this_player.setVerticalMovement(0);
            //for (Entity entity : entities)
                //if (!movingDiagonalOnScreen){
                this_player.move(delta);
           }                 
           
            game.setThisPlayer(this_player);
            game.setCollisionXY(collisionPoint_x,collisionPoint_y);                
        
        
    }    
    

 /**
 *Calculates if there was map collision and handles it by setting new position of the carEntity object.
  * <br>Map collision means: colliding with walls <b>BUT ALSO</b> colliding with free tile boundaries(free to drive in the direction of this boundary)<br> so we can spot that the car 
  * has entered a new tile (update active_tile).Active Tile and collision check depends on moving forward/backwards/the angle<br> and neighbour tiles (+free direction boundaries/walls) of the active tile! 
 *<p>It uses getters to init locally f.e.:active_tile player,coordinates player,booleans,angle,current_car_image..
  * <br>Setters: it sets the new position of the car when colliding (updates the carEntity object)
 * <br>
 * @param  game Game-object for using its getters/setters.
 * @see Tile
  * @see booleans
  * @see Game.InputHandler#keyPressed(KeyEvent)

 */          
public static void mapCollisionCheck(Game game){
           
       
       //Game g,CarEntity this_player,int previous_active_tile,double x,double y,HashMap map_tiletype_switchNumber,HashMap map_tileId_tileObject,int active_tile_this_player,booleans bol,int angle,BufferedImage current_car_image){
        
       
       
    //eerst apart voor de duidelijkheid
    //later kan x en y weg want je hebt die enkel nodig om in het begin gelijk te zetten aan collision vars
    //CarEntity getCarEntity();
    current_car_image=game.getCurrentCarImage();
    this_player=game.getThisPlayer();
    double x=this_player.getX();
    double y=this_player.getY();
    active_tile_this_player=game.getActiveTile();    
    previous_active_tile=game.getPreviousActiveTile();
    bol=game.getBooleans();
    angle=game.getAngle();
    //HashMap getMap_tiletype_switchNumber();

    //HashMap getMap_tileId_tileObject();   
       
       

       
       
       //OPMERKING !!!
        //sinds het gebruik van previous_x bij carcollision
        //zal deze methode ook wat vereenvoudigd kunnen worden(tenzij men botseffect wilt crëeren)
        //=>afh van angle enzo...zelf coördinaten bijstellen
        //geldt ook voor carcollision...als men echt een botsing wilt zien ipv stilstaan=>per situatie zelf definiëren
        //dat is voor later

        //volledig uitgetekend..en geïmplementeerd

        movingLeftOnScreen = bol.getmovingLeftOnScreen();
        movingRightOnScreen = bol.getmovingRightOnScreen();
        movingUpOnScreen = bol.getmovingUpOnScreen();
        movingDownOnScreen = bol.getmovingDownOnScreen();
        movingDiagonalOnScreen = bol.getmovingDiagonalOnScreen();

        driving_forward=bol.getvooruitrijden();
        driving_backwards=bol.getachteruitrijden();
                
        Tile active_tileTile = (Tile)map_tileId_tileObjectCol.get(active_tile_this_player);
        //buren ophalen
        TileTypeNeighbours active_tileTTN=(TileTypeNeighbours) active_tileTile.ttn;
        int putback=1;
        int tile_width=active_tileTile.width;
        int tile_height=active_tileTile.height;
        

        int angle_fake_90=80;
        int angle_fake_270=260;
        //x en y vervangen want heb globale collisionpoint nodig
        collisionPoint_x=x;
        collisionPoint_y=y;

        //hij zal coordinaat van linkerbovenhek resetten bij collision
        //maar als je achteruit rijdt tegen ene muur moet de achterkant collision geven 
        //dusmoet je correctiefactor instellen (hoger resetten op het scherm,anders lijkt het alsof de auto 
        //zich onder de tile bevindt ipv net boven

        int correctie_width=0; 
        int correctie_height=0;
        //correctie wordt enkel ingevuld als er zich een speciale situatie voordoet
        //(zie onder,eerste controle per case van de switch)
        
        //correction of collisionPoint
        if(active_tile_this_player != 0){
        
        //eerst collision params goedzetten voor diagonale (normaal kan dat i nde switch maar dan moet men overal zelfde code schrijven
        correctie_width=current_car_image.getWidth();
        correctie_height=current_car_image.getHeight();                        
        if(((angle >0)&&(angle < angle_fake_90)&&(driving_backwards))||((angle >180)&&(angle < angle_fake_270)&&(driving_forward))){
               collisionPoint_x+=correctie_width;
               collisionPoint_y+=correctie_height;                        
        }else if(((angle > angle_fake_90)&&(angle <180)&&(driving_forward))||((angle >angle_fake_270)&&(angle <360)&&(driving_backwards))||((driving_forward)&&(angle==180))||((driving_backwards)&&(angle==0))){ 
               collisionPoint_x+=correctie_width;
                        
        }else if(((angle > angle_fake_90)&&(angle <180)&&(driving_backwards))||((angle >angle_fake_270)&&(angle <360)&&(driving_forward))||((driving_forward)&&(angle==angle_fake_270))||((driving_backwards)&&(angle==angle_fake_90))){ 
               collisionPoint_y+=correctie_height;                        
        }

        
        //controle op niet diagonale ->collision point
        //+afhandeling collision voor alle hoeken
        
            previous_active_tile=active_tile_this_player;
            //System.out.println("0 tile");
            switch (tileTypeCheck(active_tile_this_player)){
            
            //steeds een x en y waarde vergelijken van de tile met positie van de auto (overschreden? => collision)
            //als de tegenovergestelde x en y waarde overschreden is : nieuwe tile

             //x en y elk een if/else geven (nooit buurrichtingen in 1 2delige-if/else structuur)
            //geen onlogische waarschuwing aangezien men 2 richtingen per collision hebt en 2 richtingen om actieve tile te triggeren
            case 1:
                //horizontal type

                //collision detection
               

                
                if (collisionPoint_y > (active_tileTile.y + tile_height)){
                    if(movingDiagonalOnScreen){
                    this_player.setXY(this_player.getX(), active_tileTile.y+(tile_height)-putback-correctie_height);
                    }else{                    
                    this_player.setXY(collisionPoint_x, active_tileTile.y+(tile_height)-putback-correctie_height);
                    System.out.println("collision");
                    }
                }else if (collisionPoint_y < active_tileTile.y){
                    if(movingDiagonalOnScreen){
                    this_player.setXY(this_player.getX(), active_tileTile.y+putback);                        
                    }else{
                    this_player.setXY(collisionPoint_x, active_tileTile.y+putback);    
                    }
                    
                    System.out.println("collision");
                    
                }
                
                if(collisionPoint_x < active_tileTile.x){
                    active_tile_this_player=active_tileTTN.getLeft();
                    //tileChanged=true;
                }else if(collisionPoint_x > (active_tileTile.x + tile_width)){
                    active_tile_this_player=active_tileTTN.getRight();
                    //tileChanged=true;
                }



            break;

            case 2:
                //vertical type

           
                //resterende mogelijkheden checken als trigger voor nieuwe actieve tile

                if (collisionPoint_x > (active_tileTile.x + tile_width)){
                    if(movingDiagonalOnScreen){
                    this_player.setXY((active_tileTile.x+(tile_width)-correctie_width-putback),this_player.getY());
                    }else{                                        
                    this_player.setXY((active_tileTile.x+(tile_width)-correctie_width-putback),collisionPoint_y);
                    System.out.println("collision");
                    }  
                }else if(collisionPoint_x < active_tileTile.x){
                    if(movingDiagonalOnScreen){
                    this_player.setXY(active_tileTile.x+correctie_width+putback,this_player.getY());
                    }else{                                                            
                    this_player.setXY(active_tileTile.x+correctie_width+putback,collisionPoint_y);
                    System.out.println("collision");
                    }
                }
                //collision detection
                //triggers voor nieuwe actieve tile
                if(collisionPoint_y < active_tileTile.y){
                    active_tile_this_player=active_tileTTN.getTop();
                    //tileChanged=true;
                }else if(collisionPoint_y > (active_tileTile.y + tile_height)){
                    active_tile_this_player=active_tileTTN.getBottom();
                    //tileChanged=true;
                }
            break;

            case 3:
                //K1 type

                //collision detection
                if (collisionPoint_x > (active_tileTile.x + tile_width)){
                    if(movingDiagonalOnScreen){
                    
                    this_player.setXY((active_tileTile.x+(tile_width)-correctie_width-putback),this_player.getY());
                    }else{                        
                    this_player.setXY((active_tileTile.x+(tile_width)-correctie_width-putback),collisionPoint_y);
                    
                    }
                    System.out.println("collision");
                }else if(collisionPoint_x < active_tileTile.x){
                    active_tile_this_player=active_tileTTN.getLeft();
                    //tileChanged=true;
                }
                
                        
                
                if(collisionPoint_y < active_tileTile.y){
                    if(movingDiagonalOnScreen){
                    this_player.setXY(this_player.getX(), active_tileTile.y+putback);
                    
                    }else{                                            
                    this_player.setXY(collisionPoint_x, active_tileTile.y+putback);
                    }
                    System.out.println("collision");
                    
                
                }else if(collisionPoint_y > (active_tileTile.y + tile_height)){
                    active_tile_this_player=active_tileTTN.getBottom();
                    //tileChanged=true;
                }

            break;

            case 4:
                 //K2 type

                //collision detection
                if (collisionPoint_x < active_tileTile.x){
                    if(movingDiagonalOnScreen){
                    
                    this_player.setXY(active_tileTile.x+putback,this_player.getY());
                    }else{                                                                                    
                    this_player.setXY(active_tileTile.x+putback,collisionPoint_y);
                    }
                    System.out.println("collision");
                }else if(collisionPoint_x > (active_tileTile.x+tile_width)){
                    active_tile_this_player=active_tileTTN.getRight();
                 //   tileChanged=true;
                } 
                
                
                if(collisionPoint_y < active_tileTile.y){
                    if(movingDiagonalOnScreen){
                    this_player.setXY(this_player.getX(), active_tileTile.y+putback);
                    }else{                                                                
                    this_player.setXY(collisionPoint_x, active_tileTile.y+putback);
                    }
                    System.out.println("collision");
                    
                }else if (collisionPoint_y > (active_tileTile.y + tile_height)){
                    active_tile_this_player=active_tileTTN.getBottom();
                  //  tileChanged=true;
                }
            break;

            case 5:
                 //K3 type
                  
                
                if(collisionPoint_x > (active_tileTile.x + tile_width)){
                    active_tile_this_player=active_tileTTN.getRight();
                  //  tileChanged=true;
                }else if (collisionPoint_x < active_tileTile.x){
                    if(movingDiagonalOnScreen){
                    
                    this_player.setXY(active_tileTile.x+putback,this_player.getY());
                    }else{                                                            
                    this_player.setXY(active_tileTile.x+putback,collisionPoint_y);
                    }
                    System.out.println("collision");
                }

                //triggers voor nieuwe actieve tile
                if(collisionPoint_y < active_tileTile.y){
                    active_tile_this_player=active_tileTTN.getTop();
                    //tileChanged=true;
                }else if (collisionPoint_y > (active_tileTile.y + tile_height)){
                    if(movingDiagonalOnScreen){
                    this_player.setXY(this_player.getX(), active_tileTile.y+(tile_height)-correctie_height-putback);
                    
                    }else{                                                            
                    this_player.setXY(collisionPoint_x, active_tileTile.y+(tile_height)-correctie_height-putback);
                    }
                    System.out.println("collision");
                }
                
            break;

            case 6:
                 //K4 type
                //collision detection
                if (collisionPoint_y > (active_tileTile.y + tile_height)){
                    if(movingDiagonalOnScreen){
                    
                    this_player.setXY(this_player.getX(), active_tileTile.y+(tile_height)-correctie_height-putback);
                    }else{                                  
                    this_player.setXY(collisionPoint_x, active_tileTile.y+(tile_height)-correctie_height-putback);
                    }
                    System.out.println("collision");
                }else if(collisionPoint_y < active_tileTile.y){
                    active_tile_this_player=active_tileTTN.getTop();
                  //  tileChanged=true;
                }
                
                
                if(collisionPoint_x < active_tileTile.x){
                    active_tile_this_player=active_tileTTN.getLeft();
                  //  tileChanged=true;
                }
                else if (collisionPoint_x > (active_tileTile.x + tile_width)){
                    if(movingDiagonalOnScreen){
                    this_player.setXY((active_tileTile.x+(tile_width)-correctie_width-putback),this_player.getY());
                    
                    }else{                                  
                    this_player.setXY((active_tileTile.x+(tile_width)-correctie_width-putback),collisionPoint_y);
                    }
                    System.out.println("collision");
                    
                }


                //triggers voor nieuwe actieve tile

            break;

            default:
                System.out.println("error geen type gevonden");
                break;
        }
        
            game.setThisPlayer(this_player);
            
        }else{
            active_tile_this_player=previous_active_tile;
        }
        game.setCollisionXY(collisionPoint_x,collisionPoint_y);
        game.setActiveTile(active_tile_this_player);

        //System.out.println("active tile NA SWITCH: "+active_tile_this_player);


    }
    

 /**
 *Calculates if there was car collision and handles it by setting new position of the carEntity object that was the actor of the car crash.
  * <br>It constructs 2 rectangles objects.1 for each carEntity (boundary-coordinates of their BufferedImages) and calls 
  * <br>intersects-method that returns if both rectangles touch. 
  * <br><b>Note:</b> This method is only called if car_collision is active (initial setting) AND if both cars are close to each other (see check below)
 * @param  game Game-object for using its getters/setters.(gets carEntities and sets new position of those objects)
  * @param previous_x previous coordinate used to reset position when colliding
  * @param previous_y previous coordinate used to reset position when colliding
 * @see Tile
  * @see Game#carsCloseToEachOther()
  * @see Game#gameLoop()
  * @see Game.InputHandler#keyPressed(KeyEvent)
  * */
    //map collision wordt elke loop gecheckt dus moet men hier geen getters meer oproepen van de game klasse
public static void carCollisionCheck(Game game,double previous_x,double previous_y){
         current_car_image=game.getCurrentCarImage();
        this_player=game.getThisPlayer();
        opponent=game.getOpponent();
       //enkel nog voor diagonale angels verfijnen(prentje afbeelding is groter dan de auto die je ziet dus 
       //botst al wanneer ze nog niet tegen elkaar rijden...dus -constante*x,-constante*y (+/-tekens afh van hoek)
       Rectangle rectangle_bounds_img_this_player;
       if(movingDiagonalOnScreen){
           rectangle_bounds_img_this_player = new Rectangle((int)this_player.getX()-5,(int)this_player.getY()-5,current_car_image.getWidth(),current_car_image.getHeight());
       }else{
           rectangle_bounds_img_this_player = new Rectangle((int)this_player.getX(),(int)this_player.getY(),current_car_image.getWidth(),current_car_image.getHeight());
       }
      Rectangle rectangle_bounds_img_opponent = new Rectangle((int)opponent.getX(),(int)opponent.getY(),((BufferedImage)map_angleId_bufferedImageObjectCol.get(opponent.getAngle())).getWidth(),((BufferedImage)map_angleId_bufferedImageObjectCol.get(opponent.getAngle())).getHeight());
          if (rectangle_bounds_img_opponent.intersects(rectangle_bounds_img_this_player)) {
            System.out.println("CAR COLLISION,resetting position");
            this_player.setXY(previous_x,previous_y);
            game.setThisPlayer(this_player);   
            //carcollides=true;
           // bufferScreen.drawString("!!!! car collides !!!!:", 200,385);
            
          }     
  
 }    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
 
}

